#include <GameEngine/Maps/displacement.h>



#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//=====================================================================


Q_DECLARE_OPERATORS_FOR_FLAGS(Displacement::DisplacementTypes)

//! Convert a displacement type into the corresponding index
/*!
 *  type = Inaccessible => 0<br>
 *  type = Walkable => 1<br>
 *  type = Swimable => 2<br>
 *  type = Flyable => 3<br>
 *
 @param type The displacement type to convert
 @return The corresponding index
 */
int Displacement::displacement_to_index(DisplacementType type) {
	if ( type == Inaccessible ) return 0;
	if ( type == Walkable ) return 1;
	if ( type == Swimable ) return 2;
	if ( type == Flyable ) return 3;
	return -1;
}

//! Convert an index into the corresponding displacement type
/*!
 *  index = 1 => Walkable<br>
 *  index = 2 => Swimable<br>
 *  index = 3 => Flyable<br>
 *  index = ? => Inaccessible
 *
 @param index The index to convert
 @return The corresponding displacement type
 */
Displacement::DisplacementType Displacement::index_to_displacement(int index) {
	if ( index == 1 ) return Walkable;
	if ( index == 2 ) return Swimable;
	if ( index == 3 ) return Flyable;
	return Inaccessible;
}

//=====================================================================

//! Constructor
/*!
 @param types The set of displacement types on which we should iterate
 */
DisplacementTypesIterator::DisplacementTypesIterator(const Displacement::DisplacementTypes& types) : types_(&types), index_(-1), max_index_(DisplacementTypeCount-1) {
	// Get the maximum index
	while ( types_->testFlag(Displacement::index_to_displacement(max_index_)) == false ) {
		// Get previous index, if any
		--max_index_;
		if ( max_index_ < 0 ) break;
	}

	// Get to the first available index
	next();
}

//! Copy constructor
/*!
 @param rhs The iterator to copy
 */
DisplacementTypesIterator::DisplacementTypesIterator(const DisplacementTypesIterator& rhs) : types_(rhs.types_), index_(rhs.index_), max_index_(rhs.max_index_) {}

//! Assignment operator
/*!
 @param rhs The iterator to copy
 @return A reference to this iterator
 */
DisplacementTypesIterator& DisplacementTypesIterator::operator=(const DisplacementTypesIterator& rhs) {
	if ( &rhs != this ) {
		types_ = rhs.types_;
		index_ = rhs.index_;
		max_index_ = rhs.max_index_;
	}
	return *this;
}


//! Destructor
DisplacementTypesIterator::~DisplacementTypesIterator() {}

//! Find if more types of displacement are available on the set of displacement types
/*!
 @return True if more types of displacement are available, false otherwise
 */
bool DisplacementTypesIterator::more() const {
	return ( index_ <= max_index_ );
}

//! Head to the next available displacement type
void DisplacementTypesIterator::next() {
	++index_;
	if ( index_ > max_index_ ) return;

	// Check if current index is valid
	if ( types_->testFlag(Displacement::index_to_displacement(index_)) ) return;

	// If current index is invalid, head to the first valid index
	next();
}

//! Compute the current type of displacement
/*!
 @return The current type of displacement
 */
Displacement::DisplacementType DisplacementTypesIterator::cur() const {
	return Displacement::index_to_displacement(index_);
}


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
